#encoding: UTF-8

require 'rake'
require 'rake/clean'
require 'rubygems/package_task'
require 'rdoc/task'
require 'rake/testtask'
require 'fileutils'
require 'set'

spec = Gem::Specification.new do |s|
  s.name = 'recipeminer'
  s.version = '0.0.1'
  s.has_rdoc = true
  s.extra_rdoc_files = ['README', 'LICENSE']
  s.summary = 'Your summary here'
  s.description = s.summary
  s.author = ''
  s.email = ''
  # s.executables = ['your_executable_here']
  s.files = %w(LICENSE README Rakefile) +
      Dir.glob("{bin,config,lib,main,spec}/**/*")
  s.require_path = "lib"
  s.bindir = "bin"
end

Gem::PackageTask.new(spec) do |p|
  p.gem_spec = spec
  p.need_tar = true
  p.need_zip = true
end

RDoc::Task.new do |rdoc|
  files =['README', 'LICENSE', 'lib/**/*.rb', 'main/**/*.rb']
  rdoc.rdoc_files.add(files)
  rdoc.main = "README" # page to start on
  rdoc.title = "recipeminer Docs"
  rdoc.rdoc_dir = 'doc/rdoc' # rdoc output folder
  rdoc.options << '--line-numbers'
end

namespace :crawling do
  desc 'Start (or continue) crawling of the JSON-serialisations of the chefkoch.de recipes'
  task :chefkoch_json, :max, :max_add do |t, args|
    require 'src/main/ruby/main/init'
    require 'lib/crawling'
    key_translation = {:max => :max_recipe_count, :max_add => :max_additional_recipes}
    opts = Hash.new
    args.to_hash.each_pair do |k, v|
      case v
        when /^[Nn]il$/ then
          opts[key_translation[k]] = nil
        when /^\d+$/ then
          opts[key_translation[k]] = v.to_i
        else
          raise "Limit argument not recognised: '#{v}'"
      end
    end
    Crawling::ChefkochCrawler.new.sequential_crawl(opts)
  end

  desc 'Download a single chefkoch-recipe JSON serialisation indtified by its ShowID'
  task :single_ck_json, :id, :show_id do |t, args|
    unless args[:show_id].start_with? args[:id]
      raise "Inconsistency between ID and ShowID!"
    end
    require 'src/main/ruby/main/init'
    require 'lib/crawling'
    opts = Hash.new
    args.to_hash.each_pair do |k, v|
      case v
        when /^\d+$/ then
          opts[k] = v.to_i
        else
          raise "Limit argument not recognised: '#{v}'"
      end
    end
    Crawling::ChefkochCrawler.new.single_download(opts[:id], opts[:show_id])
  end

  desc 'Show information of current crawling state'
  task :show_state do
    require 'src/main/ruby/main/init'
    java_import [de.recipeminer.persistence.Db4oHelpers,
                 de.recipeminer.crawling.chefkoch.ChefkochCrawlingState]
    state = ChefkochCrawlingState.instance
    puts "# of crawled JSON recipes: #{state.crawled_count}"
    puts "# of duplicate ShowIds during crawling process: #{state.duplicate_count}"
    puts "# of failes JSON downloads: #{state.failed_downloads.size}"
    puts "next query index: #{state.last_query_index}"
    Db4oHelpers.current_database
  end

  namespace :admin do
    task :update_uuids do
      require 'src/main/ruby/main/init'
      require 'lib/workflows'
      update = Workflow::UpdateUUIDs.new(/(\d+$)/, 'CK#§')
      update.run
      Db4oHelpers.current_database.close_all_sessions
    end

    task :list_json do
      require 'src/main/ruby/main/init'
      java_import [de.recipeminer.persistence.Db4oHelpers,
                   de.recipeminer.crawling.chefkoch.ChefkochJsonRecipe]
      container = Db4oHelpers.current_database
      begin
        container.query(ChefkochJsonRecipe.java_class).each do |r|
          puts r.to_java.to_string
        end
      ensure
        Db4oHelpers.current_database.close_all_sessions
      end
    end
  end
end

namespace :db4o do
  desc 'List the objects persisted in the default database'
  task :list do |t|
    require 'src/main/ruby/main/init'
    java_import de.recipeminer.persistence.Db4oHelpers
    java_import(java.lang.Thread) { 'JThread' }
    jruby_loader = JThread.current_thread.context_class_loader
    db = Db4oHelpers.current_database
    begin
      empty_classes = Set.new
      class_query = db.java_method(:query, [java.lang.Class])
      db.ext.stored_classes.each do |cls|
        java_class = jruby_loader.load_class(cls.name)

        result = class_query.call(java_class)
        if result.size > 0
          puts "#{java_class.name}: #{result.size} objects"
        else
          empty_classes.add(java_class.name)
        end
      end
      unless empty_classes.empty?
        puts "Known classes with no persisted instances:\n#{empty_classes.join("\n")}"
      end
    ensure
      db.close
    end
  end
end

namespace :test do
  desc 'Run all Test/Unit-Tests'
  task :run_all do
    require 'ruby-debug'
    require 'rubygems'
    gem 'test-unit'
    require 'test/unit'

    test_dir = File.join(Init::project_home_path, 'src', 'test', 'ruby')
    exit Test::Unit::AutoRunner.run(true, test_dir)
  end
end


module RakeTools
  class << self
    def reset_db_file(base_path)
      path = File.join(base_path, 'recipeminer.db4o')
      puts "Resetting db4o file: #{path}"
      File.delete(path) if File.exists?(path)
      FileUtils.touch(path)
    end
  end
end
